import re
from datetime import datetime, timedelta

# 这是日志行示例
# 可能是，时间信息、紧接着日志内容
# [2025-10-10 19:29:59.358]# RECV ASCII/31 from 192.168.0.200 :32810 <<<
# �yRW2:410.5mm

# 可能是两个时间信息，没有内容
# [2025-10-10 19:29:58.761]# Client 192.168.0.200 :32809 offline.
# [2025-10-10 19:29:59.150]# Client 192.168.0.200 :32810 online.


def parse_log_line(line):
    """
    解析单行日志，提取时间戳、客户端IP和消息内容
    支持原始字节流内容的识别

    参数:
        line (str): 单行日志内容

    返回:
        dict: 包含解析结果的字典，格式为:
        {
            'timestamp': datetime对象,
            'ip': str,
            'port': str,
            'message': str
        }
    """

    # 删除原始数据的最后换行符
    line = line.rstrip("\n")

    # 打印原始数据
    # print("原始数据:", line)

    # 正则表达式匹配时间戳、IP和消息 - 支持两种日志格式
    pattern1 = r"^\[(.*?)\]# RECV ASCII/\d+ from (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) :(\d+) <<<\s*(.*)$"
    pattern2 = r"^\[(.*?)\]# Client (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}) :(\d+) (offline|online)\.$"
    if not line.strip():  # 检测空行并跳过
        return {
            "timestamp": "",
            "ip": "",
            "port": "",
            "message": "",
        }

    else:
        match = re.match(pattern1, line.strip())
        if match:
            timestamp_str, ip, port, message = match.groups()
            message = message.strip()

        else:
            match = re.match(pattern2, line.strip())
            if not match:
                return {
                    "timestamp": "",
                    "ip": "",
                    "port": "",
                    "message": "",
                }
            timestamp_str, ip, port, message = match.groups()
            message = f"Client {ip}:{port} {message}"
        try:
            timestamp = datetime.strptime(timestamp_str, "%Y-%m-%d %H:%M:%S.%f")
        except ValueError:
            return None

    # 保持原始消息内容，不进行字节流解码处理
    return {"timestamp": timestamp, "ip": ip, "port": port, "message": message}


def detect_long_intervals(logs, threshold=timedelta(seconds=2)):
    """
    检测日志中时间间隔超过阈值的记录

    参数:
        logs (list): 已解析的日志列表
        threshold (timedelta): 时间间隔阈值，默认为5秒

    返回:
        list: 包含异常间隔日志对的列表，每个元素是(prev_log, current_log)
    """
    anomalies = []
    for i in range(1, len(logs)):
        prev_log = logs[i - 1]
        current_log = logs[i]
        # print(f"{prev_log['timestamp']} - {current_log['timestamp']}")
        interval = current_log["timestamp"] - prev_log["timestamp"]
        if interval > threshold:
            anomalies.append((prev_log, current_log))
    return anomalies


def process_log_file(input_file):
    """
    处理日志文件，解析所有有效行并检测异常间隔

    参数:
        input_file (str): 输入文件路径

    返回:
        tuple: (解析结果列表, 异常间隔列表)
    """
    results = []

    with open(input_file, "r", encoding="utf-8", errors="ignore") as f:
        for line_num, line in enumerate(f, 1):
            parsed = parse_log_line(line)
            if parsed:
                results.append(parsed)
            else:
                print(f"**警告: 第{line_num}行格式不正确，跳过处理: {line.strip()}")

    # 过滤掉无效的时间戳记录（timestamp不是datetime对象）
    valid_results = [log for log in results if isinstance(log["timestamp"], datetime)]

    # 按时间戳排序
    # valid_results.sort(key=lambda x: x["timestamp"])

    # 检测异常间隔
    anomalies = detect_long_intervals(valid_results)

    return valid_results, anomalies


def main():
    import sys

    if len(sys.argv) != 2:
        print("使用方法: python log_parser.py <输入文件>")
        sys.exit(1)

    input_file = sys.argv[1]
    parsed_logs, anomalies = process_log_file(input_file)
    print("\n检测到的异常间隔(>2秒):")
    print("{:<30} {:<30} {:<15}".format("前一时间戳", "当前时间戳", "间隔秒数"))
    print("=" * 150)

    for prev_log, current_log in anomalies:
        interval = current_log["timestamp"] - prev_log["timestamp"]
        print(
            "{:<30} {:<40} {:<15.3f}".format(
                prev_log["timestamp"].strftime("%Y-%m-%d %H:%M:%S"),
                current_log["timestamp"].strftime("%Y-%m-%d %H:%M:%S"),
                interval.total_seconds(),
            )
        )

        # 打印前一行和当前行的内容
        print("{:<30}\n{:<30}".format(prev_log["message"], current_log["message"]))

        # 打印分隔线
        print("-" * 150)


if __name__ == "__main__":
    # 执行代码前，先执行clear 清除屏幕
    try:
        import os

        os.system("cls")
    except:
        pass

    main()
